/********************************************************************
 * @file     arw97420.h
 * @brief    arw97420芯片的stm32平台驱动库
 *
 * @author   lzy (lllzzzyyy@buaa.edu.cn)
 * @date     2025-02-13
 * @url      https://sinlatansen.site
 *
 *
 *   █████╗ ██████╗ ██╗    ██╗ █████╗ ███████╗██╗  ██╗██████╗  ██████╗
 *  ██╔══██╗██╔══██╗██║    ██║██╔══██╗╚════██║██║  ██║╚════██╗██╔═████╗
 *  ███████║██████╔╝██║ █╗ ██║╚██████║    ██╔╝███████║ █████╔╝██║██╔██║
 *  ██╔══██║██╔══██╗██║███╗██║ ╚═══██║   ██╔╝ ╚════██║██╔═══╝ ████╔╝██║
 *  ██║  ██║██║  ██║╚███╔███╔╝ █████╔╝   ██║       ██║███████╗╚██████╔╝
 *  ╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝  ╚════╝    ╚═╝       ╚═╝╚══════╝ ╚═════╝
 *
 ********************************************************************/

#ifndef __ARW97420__H__
#define __ARW97420__H__

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32f4xx_hal.h"
/* TODO: 是否启用 FreeRTOS */
// #include "FreeRTOS.h"

#define ARW_CONFIG_DATA_SIZE 13   /**< 射频配置数据长度 */
#define ARW_SPI_SHORT_DATA_SIZE 2 /**< SPI短帧数据长度 */
#define ARW_SPI_HEADER_COUNT 12   /**< SPI帧头位数 */
#define ARW_SPI_CONTROL_COUNT 2   /**< SPI预留控制位数 */

/* TODO: 提供延迟函数 */
// #define ARW_DELAY_NS(ns)
// #define ARW_DELAY_US(us)
#ifndef ARW_DELAY_NS
#error "请提供延迟函数"
#endif

/* TODO: 提供打印函数 */
// #define ARW_PRINTF(fmt, ...)
#ifndef ARW_PRINTF
#error "请提供打印函数"
#endif

/* 临界区 */
#if __has_include("FreeRTOS.h")
#define ARW_ENTER_CRITICAL()  \
    do {                      \
        taskENTER_CRITICAL(); \
        __disable_irq();      \
    } while (0)
#define ARW_EXIT_CRITICAL()  \
    do {                     \
        taskEXIT_CRITICAL(); \
        __enable_irq();      \
    } while (0)
#else
#define ARW_ENTER_CRITICAL() __disable_irq()
#define ARW_EXIT_CRITICAL() __enable_irq()
#endif

#define ARW_SPI_SPEED_MHZ 15 /**< spi速率, 最大20MHz */

/* TODO: 根据实际硬件连接情况修改 */
#define ARW_GPIO_CLK_ENABLE()         \
    do {                              \
        __HAL_RCC_GPIOA_CLK_ENABLE(); \
        __HAL_RCC_GPIOB_CLK_ENABLE(); \
        __HAL_RCC_GPIOC_CLK_ENABLE(); \
        __HAL_RCC_GPIOD_CLK_ENABLE(); \
        __HAL_RCC_GPIOE_CLK_ENABLE(); \
    } while (0)

/**
 * @brief    动态内存分配
 * @details  若使用FreeRTOS, 必须使用动态内存分配。否则, 可以任选
 */
#if __has_include("FreeRTOS.h")
#define ARW_DYNAMIC_MEMORY_ENABLE 1
#else
#define ARW_DYNAMIC_MEMORY_ENABLE 0
#endif

/**
 * @enum SendMode
 * @brief 芯片发射模式
 * @details 其中只有 BFC 和 SPI_Long 可以用于配置RF参数\n
 *          SPI_Short 主要用于芯片初始化过程
 */
typedef enum SendMode {
    kArwSendModeBfc,      /**< BFC模式 */
    kArwSendModeSpiLong,  /**< SPI长帧模式 */
    kArwSendModeSpiShort, /**< SPI短帧模式 */
} SendMode_t;

#define X_ARW_ERROR_LIST                      \
    X_ARW_ERROR(Ok, Success)                  \
    X_ARW_ERROR(ErrNullPtr, Null pointer)     \
    X_ARW_ERROR(ErrSendMode, Sendmode error)  \
    X_ARW_ERROR(ErrDataSize, Data size error) \
    X_ARW_ERROR(ErrChipMode, Chip mode error) \
    X_ARW_ERROR(ErrSpiData, Spi data error)

#define X_ARW_ERROR(code, msg) kArw##code,
/**
 * @enum ArwErr
 * @brief 错误码
 */
typedef enum ArwErr { X_ARW_ERROR_LIST } ArwErr_t;
#undef X_ARW_ERROR

/**
 * @enum ChipMode
 * @brief 芯片模式
 * @details
 *                                       TRT | TRR | SD1 | SD0            \n
 *          (0) 发射开关开启 发射电源开启     1  |  1  |  1  |  X    TX       \n
 *          (1) 开关为负载态 发射电源开启     0  |  1  |  1  |  X             \n
 *          (2) 接收开关开启 接收电源开启     0  |  0  |  X  |  1    RX       \n
 *          (3) 负载态                     X  |  X  |  0  |  0    LOAD     \n
 *
 *           1. 抽象为三种模式: 发射, 接收, 负载也就是说 (1) 其实是过渡态\n
 *           2. 每个芯片的四个通道需要是同一状态\n
 *           3. X即为不关心, 约定: X都设置为0
 */
typedef enum ChipMode {
    kArwChipModeLoad, /**< 负载模式 */
    kArwChipModeRx,   /**< 接收模式 */
    kArwChipModeTx,   /**< 发射模式 */
} ChipMode_t;

/**
 * @struct Gpio
 * @brief  GPIO配置
 */
typedef struct Gpio {
    GPIO_TypeDef* port_ptr; /**< GPIO端口指针 */
    uint16_t pin;           /**< GPIO引脚 */
} Gpio_t;

/**
 * @struct ArwHardware
 * @brief  硬件配置
 */
typedef struct ArwHardware {
    Gpio_t sdi_pin;
    Gpio_t sdo_pin;
    Gpio_t cs_pin;
    Gpio_t ld_pin;
    Gpio_t trt_pin;
    Gpio_t trr_pin;
    Gpio_t clki_pin;
    Gpio_t clko_pin;
    Gpio_t reset_pin;
} ArwHardware_t;

/**
 * @struct ArwHandle
 * @brief  芯片句柄
 */
typedef struct ArwHandle {
    uint8_t device_num;     /**< 设备号 */
    ArwHardware_t hardware; /**< 硬件配置 */
    ArwErr_t err_code;      /**< 错误码 */
    SendMode_t send_mode;   /**< 发送模式 */
    ChipMode_t chip_mode;   /**< 芯片模式 */
} ArwHandle_t;

#if ARW_DYNAMIC_MEMORY_ENABLE
/**
 * @brief 初始化
 * @param device_num 设备号
 * @param hw_ptr 硬件配置指针
 * @retrun 芯片句柄指针, 失败返回NULL
 */
ArwHandle_t* ARW97420_Init(uint8_t device_num, ArwHardware_t* hw_ptr);

/**
 * @brief 反初始化
 * @param this 芯片句柄指针
 */
void ARW97420_Deinit(ArwHandle_t* this);
#else
/**
 * @brief 初始化
 * @param this 芯片句柄指针
 * @retval 0 成功
 * @retval 1 失败
 * @note 用户需要提前为 device_num 和 hardware 赋值
 * @code
 * ArwHandle_t arw = {.device_num = 0,
 *                    .hardware = (ArwHardware_t){
 *                        .clko_pin = {.port_ptr = GPIOB, .pin = 1},
 *                        .clki_pin = {.port_ptr = GPIOB, .pin = 2},
 *                        .ld_pin = {.port_ptr = GPIOB, .pin = 3},
 *                        .cs_pin = {.port_ptr = GPIOB, .pin = 4},
 *                        .reset_pin = {.port_ptr = GPIOB, .pin = 5},
 *                        .trt_pin = {.port_ptr = GPIOB, .pin = 6},
 *                        .trr_pin = {.port_ptr = GPIOB, .pin = 7},
 *                        .sdo_pin = {.port_ptr = GPIOB, .pin = 8},
 *                        .sdi_pin = {.port_ptr = GPIOB, .pin = 9},
 *                    }};
 * if(Arw97420_Init(&arw)) {
 *   return 1;
 * }
 * @endcode
 */
uint8_t ARW97420_Init(ArwHandle_t* this);
#endif

/**
 * @brief 硬复位
 * @param this 芯片句柄指针
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t ARW97420_HardReset(ArwHandle_t* this);

/**
 * @brief 软复位
 * @param this 芯片句柄指针
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t ARW97420_SoftReset(ArwHandle_t* this);

/**
 * @brief EFuse复位
 * @param this 芯片句柄指针
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t ARW97420_EFuseReset(ArwHandle_t* this);

/**
 * @brief 获取芯片温度
 * @note 需要在 SPI_Short 模式下使用
 * @param this 芯片句柄指针
 * @param temp_ptr 温度存入的地址
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t ARW97420_GetTemp(ArwHandle_t* this, float* temp_ptr);

/**
 * @brief 设置射频参数
 * @note 可选 BFC 或者 SPI_Long 模式\n
 *       config数组发送顺序是从[0]的最高字节到[12]的最低字节
 * @param this 芯片句柄指针
 * @param config_ptr 射频参数指针
 * @param config_size 射频参数长度
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t ARW97420_SetRfConfig(ArwHandle_t* this, uint8_t* config_ptr, uint8_t config_size);

/**
 * @brief 设置发送模式
 * @param this 芯片句柄指针
 * @param next_mode 发送模式
 * @retval 0 成功
 * @retval 1 失败
 */
uint8_t ARW97420_SetSendMode(ArwHandle_t* this, SendMode_t next_mode);

/**
 * @brief 打印错误码
 */
void ARW97420_LogError(ArwHandle_t* this);

#ifdef __cplusplus
}
#endif

#endif  //!__ARW97420__H__
